﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD4Fun
{
    public class Linq4Fun
    {

        PresidentsOption[] presidentsOptions ={new PresidentsOption(1,10),
                                                new PresidentsOption(2,10),
                                                new PresidentsOption(2,50),
                                                new PresidentsOption(3,100),
                                                new PresidentsOption(4,30),
                                                new PresidentsOption(4,80),
                                                new PresidentsOption(5,200),
                                                new PresidentsOption(5,10),
                                                new PresidentsOption(6,90),
                                                new PresidentsOption(6,80),
                                                new PresidentsOption(7,10)};


        public void TestGroupByOne()
        {
            /* GroupBy第一种原型
       * 
       * 返回值为IGroupting<K,T>集合数组,每个IGroupting<k,t>包含一个(K)Key及
       * 一个拥有相同Key的集合数组T
       * 
       * 将含有相同的Key 分成一组
       * public static IEnumerable<IGrouping<K, T>> GroupBy<T, K>(
       *   this IEnumerable<T> source,
       *   Func<T, K> keySelector);
       * 
       */
            IEnumerable<IGrouping<int, PresidentsOption>> outerSequence = presidentsOptions.GroupBy(p => p.Id);
            foreach (IGrouping<int, PresidentsOption> keyGroupSequence in outerSequence)
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("....key(id):" + keyGroupSequence.Key);
                foreach (PresidentsOption presidents in keyGroupSequence)
                {
                    Console.WriteLine("id={0}...option={1}", presidents.Id, presidents.Option);
                }
            }


        }

        public void TestGroupByTwo()
        {
            /*GroupBy第二种原型
        * 
        * 功能和第一种一样,只是比较方法 comparer自定义
        * 需要实现IEqualityComparer<K>接口
        * 
        * public static IEnumerable<IGrouping<K, T>> GroupBy<T, K>(
        *   this IEnumerable<T> source,
        *   Func<T, K> keySelector,
        *   IEqualityComparer<K> comparer);
        * 
        */
            GroupByCompare compare = new GroupByCompare();
            //通过compare比较.具有相同hashCode的Key分成一组
            IEnumerable<IGrouping<int, PresidentsOption>> outerSequence = presidentsOptions.GroupBy(p => p.Id, compare);
            foreach (IGrouping<int, PresidentsOption> keyGroupSequence in outerSequence)
            {

                Console.WriteLine("-----------------------------------");
                Console.WriteLine("....key(hashCode):" + keyGroupSequence.Key);
                foreach (PresidentsOption presidents in keyGroupSequence)
                {
                    Console.WriteLine("id={0}...option={1}", presidents.Id, presidents.Option);
                }
            }

        }

        public void TestGroupByThree()
        {
            /* GroupBy第三种原型
         * 
         * 第三钟原型和第一种类似,只不过IGrouping<K, E>中E值为T的一个元素,
         * 而不是是T类型的实体对象
         * 
         * public static IEnumerable<IGrouping<K, E>> GroupBy<T, K, E>(
         *    this IEnumerable<T> source,
         *    Func<T, K> keySelector,
         *    Func<T, E> elementSelector);
         * 
         */
            IEnumerable<IGrouping<int, int>> outerSequence = presidentsOptions.GroupBy(p => p.Id, p => p.Option);
            foreach (IGrouping<int, int> keyGroupSequence in outerSequence)
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("....key(id):" + keyGroupSequence.Key);
                foreach (int options in keyGroupSequence)
                {
                    Console.WriteLine("...option={0}", options);
                }
            }
        }

        public void TestGroupByFour()
        {
            /*GroupBy第四种原型
        * 
        *
        * 第四种具有第二种和第三中功能
        * 
        *    public static IEnumerable<IGrouping<K, E>> GroupBy<T, K, E>(
        *       this IEnumerable<T> source,
        *       Func<T, K> keySelector,
        *       Func<T, E> elementSelector,
        *       IEqualityComparer<K> comparer);
        * 
        */
            GroupByCompare compare = new GroupByCompare();

            IEnumerable<IGrouping<int, int>> outerSequence = presidentsOptions
                .GroupBy(p => p.Id, p => p.Option, compare);
            foreach (IGrouping<int, int> keyGroupSequence in outerSequence)
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("....key(hashCode):" + keyGroupSequence.Key);
                foreach (int options in keyGroupSequence)
                {
                    Console.WriteLine("...option={0}", options);
                }
            }
        }

    }

    public class PresidentsOption
    {
        public int Id
        {
            get;
            set;
        }
        public int Option
        {
            get;
            set;
        }
        public PresidentsOption(int id, int option)
        {
            this.Id = id;
            this.Option = option;
        }
    }

    //实现IEqualityComparer<T>
    public class GroupByCompare : IEqualityComparer<int>
    {
        public bool Equals(int x, int y)
        {
            return (isLessFive(x) == isLessFive(y));
        }
        //小于返回1的HashCode、大于等于5的返回5的hashCode
        public int GetHashCode(int x)
        {
            int intStart = 1;
            int intCompare = 5;
            return isLessFive(x) ? intStart.GetHashCode() : intCompare.GetHashCode();
        }
        public bool isLessFive(int x)
        {
            return (x < 5);
        }
    }
}
